1、题干
给定一个只包含数字的字符串 s
,用以表示一个 IP 地址,返回所有可能从 s
获得的 有效 IP 地址 。你可以按任何顺序返回答案。
有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0
),整数之间用 '.'
分隔。
例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。
示例 1:
输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]
示例 2:
输入:s = "0000"
输出:["0.0.0.0"]
示例 3:
输入:s = "1111"
输出:["1.1.1.1"]
示例 4:
输入:s = "010010"
输出:["0.10.0.10","0.100.1.0"]
示例 5:
输入:s = "10203040"
输出:["10.20.30.40","102.0.30.40","10.203.0.40"]
提示:
0 <= s.length <= 3000
s
仅由数字组成
注意:本题与主站 93 题相同:https://leetcode-cn.com/problems/restore-ip-addresses/
2、解法1-嵌套循环
三层嵌套循环确定 IP
地址的4个子串,并检验其合法性
3、代码
var restoreIpAddresses = function (s) {
const n = s.length;
const valid = (str) => !((str.length > 1 && str[0] === '0') || +str > 255);
const res = [];
for (let i = 1; i < 4; i++) {
if (n - i < 3 || n - i > 9) continue;
for (let j = i + 1; j < i + 4; j++) {
if (n - j < 2 || n - j > 6) continue;
for (let k = j + 1; k < j + 4; k++) {
if (n - k < 1 || n - k > 3) continue;
const s1 = s.slice(0, i), s2 = s.slice(i, j);
const s3 = s.slice(j, k), s4 = s.slice(k);
if (valid(s1) && valid(s2) && valid(s3) && valid(s4)) res.push(`${s1}.${s2}.${s3}.${s4}`);
}
}
}
return res;
};
代码中的校验可以简化,但遍历次数会增加
var restoreIpAddresses = function (s) {
const valid = (str) => !(str.length < 1 || str.length > 3 || (str.length > 1 && str[0] === '0') || +str > 255);
const res = [];
for (let i = 1; i < 4; i++) {
for (let j = i + 1; j < i + 4; j++) {
for (let k = j + 1; k < j + 4; k++) {
const s1 = s.slice(0, i), s2 = s.slice(i, j);
const s3 = s.slice(j, k), s4 = s.slice(k);
if (valid(s1) && valid(s2) && valid(s3) && valid(s4)) res.push(`${s1}.${s2}.${s3}.${s4}`);
}
}
}
return res;
};
4、执行结果
5、解法2-回溯
使用回溯算法,在字符串 s
中选取3个索引作为选择路径(idxArr
),其中索引值用于将字符串 s
分割成4个 IP
子串,以子串长度作为选择列表。
注意
- 选择列表(子串长度)只有
1
、2
、3
三种选择 - 为了代码简洁性,每次递归都传入不同引用的选择路径(
idxArr
),这样可以省略撤销操作,但是消耗的内存会偏多
6、代码
var restoreIpAddresses = function (s) {
const n = s.length;
const valid = (str) => !((str.length > 1 && str[0] === '0') || +str > 255);
const res = [];
function backtrace(idxArr) {
const ln = idxArr.length, li = idxArr[ln - 1] || 0;
if (n - li < 4 - ln || n - li > 3 * (4 - ln)) return;
if (ln === 3) {
const s1 = s.slice(0, idxArr[0]), s2 = s.slice(idxArr[0], idxArr[1]);
const s3 = s.slice(idxArr[1], idxArr[2]), s4 = s.slice(idxArr[2]);
if (valid(s1) && valid(s2) && valid(s3) && valid(s4)) res.push(`${s1}.${s2}.${s3}.${s4}`);
return;
}
for (let i = 1; i <= 3; i++) backtrace([...idxArr, li + i]);
}
return backtrace([]), res;
};
7、执行结果
- 执行用时: 68 ms
- 内存消耗: 43.4 MB